/**
 * 
 */
package com.seedwill.common.query.filter;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import com.seedwill.common.persistence.OrderBy;
import com.seedwill.common.query.ScalarParaReg;
import com.seedwill.common.query.StatisticClauseItem;
import com.seedwill.common.util.ParaCheckHelper;

public abstract class AFilter implements Serializable{
	
	//public static final String ID = "id";

	public static final String IS_DELETE = "deleted";
	//改为protected使可继承使用
	protected List<Expression> filters = new ArrayList<Expression>();

	protected List<OrderBy> orders = new ArrayList<OrderBy>();

	public void add(Expression exp) {
		filters.add(exp);
	}

	public List<OrderBy> getOrders() {
		return orders;
	}

	public void setOrders(List<OrderBy> orders) {
		this.orders = orders;
	}

	public List<String> getSelectElements() {
		return selectElements;
	}

	public OrderBy getSortBy() {
		return sortBy;
	}

	public void setSortBy(OrderBy sortField) {
		this.sortBy = sortField;
	}

	public void setSelectElements(List<String> selectElements) {
		this.selectElements = selectElements;
	}

	public List<String> getDistinctElements() {
		return distinctElements;
	}

	public void setDistinctElements(List<String> distinctElements) {
		this.distinctElements = distinctElements;
	}

	public List<StatisticClauseItem> getStatisticClauseItemList() {
		return statisticClauseItemList;
	}

	public void setStatisticClauseItemList(
			List<StatisticClauseItem> statisticClauseItemList) {
		this.statisticClauseItemList = statisticClauseItemList;
	}

	public String getIdField() {
		return idField;
	}

	public void setIdField(String idField) {
		this.idField = idField;
	}

	public String getSelectFileds() {
		return selectFileds;
	}

	public void setSelectFileds(String selectFileds) {
		this.selectFileds = selectFileds;
	}

	public void addEqualTo(String field, Object value) {
		filters.add(Expression.equal(field, value));
	}

	public void addNotEqualTo(String field, Object value) {
		filters.add(Expression.notEqual(field, value));
	}

	public void addGreaterOrEqualThan(String field, Object value) {
		filters.add(Expression.greaterOrEqual(field, value));
	}

	public void addGreaterThan(String field, Object value) {
		filters.add(Expression.greaterThan(field, value));
	}

	public void addLessOrEqualThan(String field, Object value) {
		filters.add(Expression.lessOrEqual(field, value));
	}

	public void addLessThan(String field, Object value) {
		filters.add(Expression.lessThan(field, value));
	}

	public void addBetween(String field, Object low, Object high) {
		filters.add(Expression.between(field, low, high));
	}

	public void addNotBetween(String field, Object low, Object high) {
		filters.add(Expression.notBetween(field, low, high));
	}

	public void addIn(String field, Collection value) {
		filters.add(Expression.in(field, value));
	}

	public void addNotIn(String field, Collection value) {
		filters.add(Expression.notIn(field, value));
	}

	public void addIsNull(String field) {
		filters.add(Expression.nullField(field, null));
	}

	public void addNotNull(String field) {
		filters.add(Expression.notNullField(field, null));
	}

	public void addLike(String field, String value) {
		filters.add(Expression.like(field, value));
	}

	public void addNotLike(String field, String value) {
		filters.add(Expression.notLike(field, value));
	}
	
	public void addClause(String hql , Object...objects){
		//System.out.println("\n addClause: para len: " + objects.length);
		filters.add(Expression.clause(hql, objects));
	}

	public void addOrderBy(String order, boolean acending) {
		if (order == null || order.trim().equals("")) {
			// don't add this orderBy
			return;
		}
		orders.add(new OrderBy(order, acending));
	}
	
	/**
	 * 
	 */
	protected List<ScalarParaReg> sqlScalarParaReg;
	
	public List<ScalarParaReg> getSqlScalarParaReg() {
		return sqlScalarParaReg;
	}

	/**
	 * @param sqlScalarParaReg
	 */
	public void setSqlScalarParaReg(List<ScalarParaReg> sqlScalarParaReg) {
		this.sqlScalarParaReg = sqlScalarParaReg;
	}
	
	public void addScalarParaReg(ScalarParaReg p){
		if(sqlScalarParaReg == null){
			sqlScalarParaReg = new ArrayList<ScalarParaReg>();
		}
		sqlScalarParaReg.add(p);
	}
	
	public void removeScalarParaReg(ScalarParaReg p){
		sqlScalarParaReg.remove(p);
	}
	
	public void removeScalarParaReg(int pIdx){
		sqlScalarParaReg.remove(pIdx);
	}
	
	public void cleanScalarParaReg(){
		sqlScalarParaReg.clear();
	}
	
	/**
	 * 要查询出的对象
	 */
	private List<String> selectElements;
	/**
	 * 定义的distinct元素
	 */
	private List<String> distinctElements;

	/**
	 * 检查初始化select集合
	 */
	private void ifInitedSelectElements() {
		if (selectElements == null) {
			selectElements = new ArrayList<String>();
		}
	}
	
	/**
	 * 在查询条件基础上的统计任务
	 */
	private List<StatisticClauseItem> statisticClauseItemList;

	/**
	 * 增加统计任务 将额外执行 只在SQL模式下有效
	 * 
	 * @param statisticSubClause
	 */
	public void addStatisicTask(StatisticClauseItem itm) {
		if (statisticClauseItemList == null) {
			statisticClauseItemList = new ArrayList<StatisticClauseItem>();
		}
		statisticClauseItemList.add(itm);
	}

	/**
	 * 是否以distinct开头
	 * 
	 * @param src
	 * @return
	 */
	public boolean isDistinctedElement(String src) {
		return isPrefixed(src, FilterSchemaContext.DISTINCT, true, true);
	}

	/**
	 * 是否以指定的字符串开头
	 * 
	 * @param src
	 * @param preFlag
	 * @return
	 */
	private boolean isPrefixed(String src, String preFlag) {
		return isPrefixed(src, preFlag, false, false);
	}

	/**
	 * 是否以指定的字符串开头
	 * 
	 * @param src
	 * @param preFlag
	 * @param ignoreCase
	 * @return
	 */
	private boolean isPrefixed(String src, String preFlag, boolean ignoreCase) {
		return isPrefixed(src, preFlag, false, false);
	}

	/**
	 * 是否以指定的字符串开头
	 * 
	 * @param src
	 * @param preFlag
	 * @param ignoreCase
	 * @param preSrcTrimed
	 * @return
	 */
	private boolean isPrefixed(String src, String preFlag, boolean ignoreCase,
			boolean preSrcTrimed) {
		boolean flag = false;
		if (src != null && preFlag != null && preFlag.length() > 0) {
			if (ignoreCase) {
				src = src.toLowerCase();
				preFlag = preFlag.toLowerCase();
			}
			if (preSrcTrimed) {
				src = src.trim();
			}
			flag = src != null && src.startsWith(preFlag);
		}
		return flag;
	}

	/**
	 * 解析distinct查询 去掉distinct修饰符
	 * 
	 * @param src
	 * @return
	 */
	public String parseUnDistinctDesElement(String src) {
		if (isDistinctedElement(src)) {
			src = src.trim();
			src = src.substring(FilterSchemaContext.DISTINCT.length()).trim();
		}
		return src;
	}
	
	/**
	 * 增加一个FETCH对象 不能为空 只在SQL模式下有效
	 * 
	 * @param ele
	 */
	public void addSelectElement(String ele) {
		ifInitedSelectElements();
		if (ParaCheckHelper.notNull(ele)) {
			selectElements.add(ele);
		}

	}

	/**
	 * 是否已经初始化distinct List 只在SQL模式下有效
	 */
	private void ifInitedDistinctElements() {
		if (distinctElements == null) {
			distinctElements = new ArrayList<String>();
		}
	}

	/**
	 * 增加一个distinct FETCH对象 不能为空 只在SQL模式下有效
	 * 
	 * @param ele
	 */
	public void addSelectDistinctElment(String ele) {
		ifInitedDistinctElements();
		if (this.isDistinctedElement(ele)) {
			distinctElements.add(this.parseUnDistinctDesElement(ele));
		} else {
			distinctElements.add(ele);
		}
	}

	/**
	 * 增加一个FETCH对象 不能为空 只在SQL模式下有效
	 * 
	 * @param ele
	 * @param isDistinct
	 */
	public void addSelectElement(String ele, boolean isDistinct) {
		ifInitedSelectElements();
		if (ParaCheckHelper.notNull(ele)) {
			selectElements.add(ele);
			if (isDistinct) {
				if (distinctElements == null) {
					distinctElements = new ArrayList<String>();
				}
				distinctElements.add(ele);
			}
		}
	}

	/**
	 * 增加多个FETCH对象[数组] 不能为空 只在SQL模式下有效
	 * 
	 * @param eles
	 */
	public void addSelectElements(String[] eles) {
		ifInitedSelectElements();
		for (String ele : eles) {
			if (ParaCheckHelper.notNull(ele)) {
				selectElements.add(ele);
			}
		}
	}

	/**
	 * 增加多个FETCH对象[LIST] 不能为空 只在SQL模式下有效
	 * 
	 * @param eles
	 */
	public void addSelectElements(List<String> eles) {
		addSelectElements(eles, true);
	}

	/**
	 * 增加多个FETCH对象[LIST] 可设定是否检查不能为空 只在SQL模式下有效
	 * 
	 * @param eles
	 * @param foreCheckNull
	 */
	public void addSelectElements(List<String> eles, boolean foreCheckNull) {
		ifInitedSelectElements();
		if (foreCheckNull) {
			for (String ele : eles) {
				if (ParaCheckHelper.notNull(ele)) {
					selectElements.add(ele);
				}
			}
		} else {
			selectElements.addAll(eles);
		}

	}

	/**
	 * 删除FETCH对象 只在SQL模式下有效
	 * 
	 * @param ele
	 */
	public void removeSelectElement(String ele) {
		ifInitedSelectElements();
		selectElements.remove(ele);
	}

	/**
	 * 删除指定索引的FETCH对象 只在SQL模式下有效
	 * 
	 * @param eleIdx
	 */
	public void removeSelectElementAt(int eleIdx) {
		ifInitedSelectElements();
		selectElements.remove(eleIdx);
	}

	/**
	 * 清除FETCH对象 只在SQL模式下有效
	 */
	public void cleanSelectElement() {
		ifInitedSelectElements();
		selectElements.clear();
		ifInitedDistinctElements();
		distinctElements.clear();
	}

	/**
	 * SQL[MSSQL SP]分页时的标识栏位
	 */
	private String idField;

	/**
	 * SQL[MSSQL SP]分页时的排序栏位
	 */
	private OrderBy sortBy;

	/**
	 * 要取回的栏位
	 */
	private String selectFileds;

	public List<OrderBy> getOrderBys() {
		return orders;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		boolean first = true;
		for (Iterator iter = filters.iterator(); iter.hasNext();) {
			String key = (String) iter.next();
			if (first) {
				sb.append(key + " = " + iter.next());
				first = false;
			} else {
				sb.append(" && " + key + " = " + iter.next());
			}
		}

		return sb.toString();
	}

	/**
	 * @return Returns the filters.
	 */
	public List getFilters() {
		return filters;
	}

	/**
	 * @param filters
	 *            The filters to set.
	 */
	public void setFilters(List<Expression> filters) {
		this.filters = filters;
	}

	public void clear() {
		filters.clear();
		orders.clear();
	}
	protected String getSchemaName(String schema) {
		return schema.substring(schema.lastIndexOf('.') + 1);
	}
	public String getSchemaAlias(){
		String cls = "";
		if(getSchema()!=null){
			cls = getSchemaName(getSchema()).toLowerCase();
		}
		return cls;
	}
	public abstract String getSchema();

//	public class OrderBy {
//		private String orderBy;
//
//		private boolean acending;
//
//		private OrderBy(String orderBy, boolean acending) {
//			this.orderBy = orderBy;
//			this.acending = acending;
//		}
//
//		/**
//		 * @return Returns the acending.
//		 */
//		public boolean isAcending() {
//			return acending;
//		}
//
//		/**
//		 * @param acending
//		 *            The acending to set.
//		 */
//		public void setAcending(boolean acending) {
//			this.acending = acending;
//		}
//
//		/**
//		 * @return Returns the orderBy.
//		 */
//		public String getOrderBy() {
//			return orderBy;
//		}
//
//		/**
//		 * @param orderBy
//		 *            The orderBy to set.
//		 */
//		public void setOrderBy(String orderBy) {
//			this.orderBy = orderBy;
//		}
//	}

}
